/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simplemetrosystem.view.table;

import java.awt.Component;
import java.util.ArrayList;
import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import simplemetrosystem.control.EditCommandManager;
import simplemetrosystem.control.ElementManager;
import simplemetrosystem.model.Element.MetroEdge;
import simplemetrosystem.model.Element.MetroLine;
import simplemetrosystem.model.Element.MetroStation;
import simplemetrosystem.model.charlanguage.NameMap;
import simplemetrosystem.view.InformationPane;
import simplemetrosystem.view.table.Exceptions.InformationPanelException;

/**
 *
 * @author Eric Qian
 */
public class LineTable extends JTable {

    /**
     * 
     * @param infPane 
     * @param line 
     */
    public LineTable(InformationPane infPane, MetroLine line) {
        super();
        this.infPane = infPane;
        this.line = line;

        lineModel = new LineModel(infPane, line);
        this.setModel(lineModel);
        setRowSelectionAllowed(false);
        getTableHeader().setReorderingAllowed(false);
        getTableHeader().setResizingAllowed(false);

        this.setRowHeight(ROW_HEI);

        setCell();
    }

    private void setCell() {
        TableColumn valColumn = columnModel.getColumn(LineModel.COL_VAL);
        valColumn.setCellEditor(new LineValCellEditor(infPane, this));
    }
    private InformationPane infPane;
    private MetroLine line;
    private LineModel lineModel;
    public static final int ROW_HEI = 20;
}

class LineModel extends AbstractTableModel {

    public LineModel(InformationPane infPane, MetroLine line) {
        super();
        this.infPane = infPane;
        this.line = line;
        nameMap = NameMap.getInstance();
        editCommandManager = EditCommandManager.getInstance();
        initArray();
    }

    private void initArray() {
        rowCount = 6 + line.getStationsSize() * 2 + line.getEdgesSize() * 2;
        rowStationSize = line.getStationsSize();
        rowEdgeSize = line.getEdgesSize();

        int row = 0;

        rowNames = new String[rowCount];
        rowElems = new String[rowCount];

        rowNames[row] = nameMap.getName("English Name");
        rowElems[row++] = line.getName();

        rowNames[row] = nameMap.getName("Chinese Name");
        rowElems[row++] = line.getChineseName();

        rowNames[row] = nameMap.getName("Status");
        rowElems[row++] = nameMap.getName(line.getStatus());

        rowNames[row] = nameMap.getName("Color");
        rowElems[row++] = "R: " + line.getColor().getRed() +
                " G: " + line.getColor().getGreen() +
                " B: " + line.getColor().getBlue();

        rowNames[row] = nameMap.getName("Stations Number");
        rowElems[row++] = "" + line.getStationsSize();

        rowStationStart = row;
        for (int i = 0; i < line.getStationsSize(); i++) {
            if (i == 0) {
                rowNames[row] = nameMap.getName("Stations(English)");
            }
            rowElems[row++] = line.getStationAt(i).getName();
        }

        for (int i = 0; i < line.getStationsSize(); i++) {
            if (i == 0) {
                rowNames[row] = nameMap.getName("Stations(Chinese)");
            }
            rowElems[row++] = line.getStationAt(i).getChineseName();
        }

        rowNames[row] = nameMap.getName("Edges Number");
        rowElems[row++] = "" + line.getEdgesSize();

        rowEdgeStart = row;
        for (int i = 0; i < line.getEdgesSize(); i++) {
            if (i == 0) {
                rowNames[row] = nameMap.getName("Edges(English)");
            }
            rowElems[row++] = line.getEdgeAt(i).getName();
        }
        for (int i = 0; i < line.getEdgesSize(); i++) {
            if (i == 0) {
                rowNames[row] = nameMap.getName("Edges(Chinese)");
            }
            rowElems[row++] = line.getEdgeAt(i).getChineseName();
        }
    }

    @Override
    public Class getColumnClass(int column) {
        return String.class;
    }

    public int getRowCount() {
        return rowCount;
    }

    @Override
    public String getColumnName(int column) {
        if (column == COL_PRO) {
            return nameMap.getName("Property");
        } else if (column == COL_VAL) {
            return nameMap.getName("Value");
        } else {
            return "???";
        }
    }

    @Override
    public int getColumnCount() {
        return COL_COUNT;
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if ((rowIndex == ROW_NAM || rowIndex == ROW_CNAM ||
                (rowIndex >= rowStationStart && rowIndex != rowEdgeStart - 1)) && columnIndex == COL_VAL) {
            return true;
        }
        return false;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (rowIndex == ROW_NAM) {
            editCommandManager.EditLine(line, line.getName(),
                    line.getChineseName(), line.getStatus(), line.getColor());
        } else if (rowIndex == ROW_CNAM) {
            editCommandManager.EditLine(line, line.getName(),
                    line.getChineseName(), line.getStatus(), line.getColor());
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if (columnIndex == COL_PRO) {
            return rowNames[rowIndex];
        } else if (columnIndex == COL_VAL) {
            return rowElems[rowIndex];
        } else {
            return "???";
        }
    }

    /**
     * 
     * @return
     */
    public int getRowEdgeSize() {
        return rowEdgeSize;
    }

    /**
     * 
     * @return
     */
    public int getRowEdgeStart() {
        return rowEdgeStart;
    }

    /**
     * 
     * @return
     */
    public int getRowStationSize() {
        return rowStationSize;
    }

    /**
     * 
     * @return
     */
    public int getRowStationStart() {
        return rowStationStart;
    }

    /**
     * 
     * @param i
     * @return
     */
    public MetroStation getStationAt(int i) {
        return line.getStationAt(i);
    }

    /**
     * 
     * @param i
     * @return
     */
    public MetroEdge getEdgeAt(int i) {
        return line.getEdgeAt(i);
    }
    private InformationPane infPane;
    private NameMap nameMap;
    private EditCommandManager editCommandManager;
    private MetroLine line;
    private int rowCount;
    private String[] rowNames;
    private String[] rowElems;
    private int rowStationStart;
    private int rowStationSize;
    private int rowEdgeStart;
    private int rowEdgeSize;
    public static final int COL_PRO = 0;
    public static final int COL_VAL = 1;
    public static final int ROW_NAM = 0;
    public static final int ROW_CNAM = 1;
    public static final int COL_COUNT = 2;
}

class LineValCellEditor extends DefaultCellEditor {

    public LineValCellEditor(InformationPane infPane, LineTable table) {
        super(new JTextField());
        this.infPane = infPane;
        this.table = table;
        this.model = (LineModel) table.getModel();
    }

    @Override
    public Object getCellEditorValue() {
        return null;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        try {
            LineModel aModel = (LineModel) table.getModel();
            if (row >= model.getRowStationStart() && row < model.getRowEdgeStart()) {
                infPane.setFocus(InformationPane.STATION,
                        aModel.getStationAt((row - model.getRowStationStart()) % model.getRowStationSize()));
                return null;
            } else if (row >= model.getRowEdgeStart()) {
                infPane.setFocus(InformationPane.EDGE,
                        aModel.getEdgeAt((row - model.getRowEdgeStart()) % model.getRowEdgeSize()));
                return null;
            } else {
                return super.getTableCellEditorComponent(table, value, isSelected, row, column);
            }
        } catch (InformationPanelException ex) {
            ex.printStackTrace();
            return null;
        }
    }
    private InformationPane infPane;
    private LineTable table;
    private LineModel model;
}